home *** CD-ROM | disk | FTP | other *** search
/ Floppyshop 2 / Floppyshop - 2.zip / Floppyshop - 2.iso / diskmags / 0022-3.564 / dmg-0121 / news.txt / gfaexprt.asc < prev    next >
Text File  |  1997-04-16  |  28KB  |  707 lines

  1.  
  2.                        GFA PROGRAMING HINTS & TIPS
  3.                        ===========================
  4.  
  5. These hints and tips were taken,  more or less at random, from a brilliant 
  6. disc by Han Kempen. It's called the GFA Expert disc and contains a massive 
  7. 1st  word  file  which prints out into a 120+ page,  2nd  manual  for  GFA 
  8. version 3 users.  It contains everything the GFA manual left out and more. 
  9. To  back  up the examples in the manual are lots of routines that  can  be 
  10. merged with your own programs.
  11.  
  12. The  author  has  placed  these files into the  public  domain  and  given 
  13. permission for extracts to be used in articles etc. While it is OK to pass 
  14. copies  of the disc on to friends,  public domain libraries must  get  his 
  15. written permission to distribute the disc. As far as I know, Caledonia  is
  16. the only PD library with the necessary permission to distribute this disc.
  17.  
  18.                                 ~~~OOOO~~~
  19.  
  20. There are several ways to (re)start your computer. The obvious one is to
  21. switch the ST off, wait a few seconds (15 seconds with a 1040 ST!), and
  22. switch on again. This is called a "cold" or "hard" reset. Your computer
  23. suffers a little, and it takes some time. If you use the reset-button on
  24. your ST, you perform a "warm" or "soft" reset. The operating system
  25. automatically performs a warm reset if you switch between Low and Medium
  26. resolution on the desktop. If you suspect a program of changing system
  27. variables, you should always use a cold reset. After a warm reset the
  28. system variables in low memory are not initialised again. Garbage will
  29. stay there and will undoubtedly lead to interesting effects. You can
  30. perform both a warm and a cold reset from GFA-Basic with the following
  31. Procedures :
  32.      PROCEDURE coldstart
  33.        SLPOKE &H420,0
  34.        SLPOKE &H426,0         ! probably not necessary
  35.        SLPOKE &H43A,0
  36.        ~XBIOS(38,L:LPEEK(4))
  37.      RETURN
  38.      '
  39.      PROCEDURE warmstart
  40.        ~XBIOS(38,L:LPEEK(4))
  41.      RETURN
  42.  
  43. If you would like to boot from your second (external) drive B, try :
  44.      SLPOKE &H446,1      ! boot from drive B after next reset
  45.      @warmstart
  46.  
  47.                                 ~~~OOOO~~~
  48.  
  49. With GEMDOS-function 48 (Sversion) you can find the version of your
  50.  
  51. GEMDOS. For both the old TOS and the Blitter-TOS &H1300 (version 0.19) is
  52. returned. The French Turbo-DOS has version 0.20 and the new Rainbow TOS of
  53. 1988 has version 0.21.
  54. Another way to find out the version of TOS uses the system header of TOS
  55. (not necessarily located in ROM!) :
  56.      adr%=LPEEK(&H4F2)
  57.      version$=HEX$(DPEEK(adr%+2))
  58. The good old ROM-TOS (1986, actually not so good) has version &H0100
  59. (1.0), the Mega-ST Blitter-TOS (1987) version &H0102 (1.2). And of course
  60. the new TOS ('Rainbow TOS') has version 1.4. You could also examine the
  61. date of your TOS-version :
  62.      date$=HEX$(LPEEK(adr%+24))
  63. My ancient TOS 1.0 has '11201985' as the date.
  64.  
  65.                                 ~~~OOOO~~~
  66.  
  67. Syntax
  68.  
  69. The parser checks for correct syntax after you press <Return>. Many typo-
  70. bugs are prevented this way. The only disadvantage is that the parser
  71. recognizes some variables as commands. It's impossible to use the follo-
  72. wing names as the first word on a line: data_byte|, dirty$, double,
  73. printer$, file%, quit!. The last one is nasty, because the parser changes
  74. the line 'quit!=FALSE' into 'QUIT!=FALSE' without warning for a syntax-
  75. error. If you now run the program you will return to the desktop when QUIT
  76. is encountered. Of course you have not lost your valuable program, because
  77. you always Save before you Run. Do you really? If the parser refuses the
  78. name of a variable, you can use LET (e.g. 'LET quit!=FALSE'). But you will
  79. have to change the name if it is a label (e.g. the label 'data1:' could be
  80. changed into '1data:' or 'd.ata1:').
  81.  
  82.                                 ~~~OOOO~~~
  83.  
  84. Folded Procedures
  85.  
  86. If you press <Control> <Help> on a Procedure-line, all Procedures follo-
  87. wing and including the current one are folded/unfolded. You can unfold all
  88. Procedures at once by putting the cursor on the first Procedure-line and
  89. pressing <Control> <Help>. I suggest you leave all Procedures in the
  90. Procedure-Library GFAXPERT.LIB folded, unless you want to examine a
  91. Procedure. The editor-commands 'Find' and 'Replace' will skip folded
  92. Procedures. Never change the Procedure-line of a folded Procedure, always
  93. unfold it first.
  94.  
  95.                                 ~~~OOOO~~~
  96.  
  97. Tab
  98.  
  99. If you press <Tab>, the cursor jumps to the next tab-position, without
  100. altering the current line. If you use <Left Shift> <Tab>, the line is
  101. filled with spaces from the current cursor-position to the next tab-
  102. position. Pressing <Right Shift> <Tab> erases all consecutive spaces to
  103. the left of the current cursor-postition. If the current cursor-position
  104. happens to be a space, this space and all spaces to the right are erased
  105. as well.
  106.  
  107.                                 ~~~OOOO~~~
  108.  
  109. Cut and Paste
  110.  
  111. If you press <Control> <P>, the current line from the cursor to the end of
  112. the line is cut, and saved in an internal buffer. <Control> <O> inserts
  113. the saved line at the current cursor-position. You can use this method to
  114. "cut and paste" a part of a line. Press <Control> <P>, then <Control> <O>
  115. to restore the original line. Move the cursor to the desired position and
  116. press <Control> <O>. Block-operations are only possible with complete
  117. lines.
  118.  
  119.                                 ~~~OOOO~~~
  120.    
  121. Llist
  122.  
  123. There has been some confusion about the following point-commands for the
  124. printer :
  125.      .p-       - point-commands are not printed
  126.      .p+       - point-commands are printed again
  127.      .llxx     - line-width
  128.      .plxx     - page-length
  129.      .pa       - form feed
  130. Sometimes the commands '.cp' and '.nu' are mentioned, but I don't know how
  131. to use these.
  132.  
  133. You can only use one point-command in one line. I use the following lines
  134. for my printer (96 characters/line in Elite-mode) :
  135.      .p-
  136.      .n4
  137.      .lr3
  138.      .ll88
  139. Save this as LLIST.LST and Merge it after the last line of a program
  140. before choosing 'Llist'. The actual listing is then printed with 80
  141. characters/line, preceded by the line-numbers (4 characters + space). If
  142. your program is longer than 10000 lines, you should use '.n5', but in that
  143. case you probably don't have time to read this. A nice touch is the
  144. automatic execution of a form feed after printing the listing.
  145.  
  146. If the listing contains special characters (ASCII-code < 32 or > 126),
  147. some of those characters might be interpreted as printer-commands. My
  148. printer switches to condensed printing after receiving the Atari-symbol.
  149. Installing the proper printer-driver (e.g. PTEPSON.PRG) will prevent that.
  150. But I never install a printer-driver because there are some serious
  151. disadvantages. Read more about it in the paragraph 'HARDCOPY'.
  152.  
  153. You can stop the printing process by pressing the 'Break'-combination
  154. <Control> <Left Shift> <Alternate>, unless Break has been disabled with
  155. 'ON BREAK CONT'. Your printer will continue printing though, until its
  156. input-buffer is empty, or until you turn the printer off.
  157.  
  158.                                 ~~~OOOO~~~
  159.  
  160. DUMP
  161.  
  162. Examine all variables in your program by typing 'DUMP' in Direct Mode.
  163. Press <CapsLock> to slow down the scrolling-speed, or press the right
  164. <Shift>-key to temporarily stop the scrolling. The Procedure Debug enables
  165. you to use DUMP during debugging. This is the best way to discover those
  166. nasty typo-bugs in a variable-name. You'll probably be surprised to see
  167. the names of deleted variables as well. Also, any variable-name you used
  168. in Direct Mode appears. All these names are SAVEd with the program! Delete
  169. all unwanted names as follows (a RAM-disk would be convenient) :
  170.      - Load the file
  171.      - Save,A (press <Return> in Fileselector)
  172.      - New
  173.      - Merge (press <Return> again)
  174.      - Save (press <Return> once more)
  175. The file could be much shorter after this operation.
  176.  
  177.                                 ~~~OOOO~~~
  178.  
  179. INKEY$
  180.  
  181. All keypresses are saved in the keyboard-buffer. If you don't want INKEY$
  182. to read an "old" key, you should first clear the buffer :
  183.      REPEAT
  184.      UNTIL INKEY$=""     ! clear keyboard-buffer
  185.      key$=""
  186.      REPEAT
  187.        key$=INKEY$       ! wait for new key
  188.      UNTIL key$<>""
  189.  
  190. In the following table you'll find a few useful decimal ASCII-codes you
  191. can use after 'key$=INKEY$'. In the third column the hexadecimal scan-code
  192. of the key is also mentioned (see paragraph 'KEYGET').
  193.  
  194.      key                   ASC(key$)       scancode
  195.      <Backspace>               8             &H0E
  196.      <Tab>                     9             &H0F
  197.      <Return> and <Enter>     13             &H1C and &H72
  198.      <Esc>                    27             &H01
  199.      <Delete>                127             &H53
  200.  
  201.      key               ASC(RIGHT$(key$))
  202.      <F1>                     59             &H3B
  203.      <F10>                    68             &H44
  204.      <Shift> <F1>             84             &H54
  205.      <Shift> <F10>            93             &H5D
  206.      <Help>                   98             &H62
  207.      <Undo>                   97             &H61
  208.      <Insert>                 82             &H52
  209.      <ClrHome>                71             &H47
  210.      <Left arrow>             75             &H4B
  211.      <Right arrow>            77             &H4D
  212.      <Up arrow>               72             &H48
  213.      <Down arrow>             80             &H50
  214.  
  215. Keys in the second part of this table return a 2-byte value after INKEY$.
  216. You only need the low byte, the high byte is &H00. That's why a Standard
  217. Global like help$ is defined as 'CHR$(0)+CHR$(98)'. Then it's easy to
  218. check if <Help> was pressed :
  219.      IF key$=help$
  220.        (...)                  ! <Help>
  221.      ENDIF
  222. Otherwise, you have to test as follows :
  223.      IF ASC(RIGHT$(key$))=98
  224.        (...)                  ! <Help>
  225.      ENDIF
  226.  
  227.                                 ~~~OOOO~~~
  228.  
  229. Setscreen (XBIOS 5)
  230.  
  231. With XBIOS 5 (Setscreen) it is possible to change the resolution from Low
  232. to Medium and from Medium to Low. Unfortunately, GEM ignores the switch,
  233. so GEM-commands (e.g. ALERT, TEXT, MOUSE) do not work properly! But you
  234. could change from Low to Medium resolution to show text on the TOS-screen
  235. with PRINT (and VT52-commands). Most users will be grateful for the
  236. improved readability of the text :
  237.      ~XBIOS(5,L:-1,L:-1,1)    ! switch from Low to Medium
  238.      (...)                    ! print text in Medium resolution
  239.      ~XBIOS(5,L:-1,L:-1,0)    ! and go back to Low
  240. If you change the resolution, the VT52-emulator is automatically
  241. initialised. You'll probably have to adjust the palette before you can
  242. read the text without sun-glasses. Don't forget to save and restore the
  243. old palette.
  244.  
  245.                                 ~~~OOOO~~~
  246.  
  247. Floppy Write Test
  248.  
  249. You are advised to switch the Write Verify test off :
  250.      SPOKE &H444,0       ! test off
  251.      SPOKE &H444,1       ! test on (default)
  252. According to experts like Dave Small and Bill Wilkinson the Verify test is
  253. a complete waste of valuable time if you write to a disk.
  254.  
  255.                                 ~~~OOOO~~~
  256.  
  257. Step Rate
  258.  
  259. You will find the current step-rate of your drive with :
  260.      PRINT DPEEK(&H440)
  261. The following values are possible :
  262.      0 -  6 ms
  263.      1 - 12 ms
  264.      2 -  2 ms
  265.      3 -  3 ms (default)
  266. The operating system only looks at this value after a reset (?). For an
  267. external 5.25"-drive you probably have to use 12 ms.
  268.  
  269.                                 ~~~OOOO~~~
  270.  
  271. Bootsector
  272.  
  273. In the following table you'll find the lay-out of a bootsector. All words
  274. are in Intel-format, except CHKSUM.
  275.  
  276.      offset    length    name
  277.  
  278.         0        2                 &H6038 = branch to bootroutine
  279.         2        6       FILLER    fill-bytes
  280.         8        3       SERIAL    serial-number of disk
  281.  
  282.        11        2       BPS       bytes/sector (512)
  283.        13        1       SPC       sectors/cluster (2)
  284.        14        2       RES       reserved sectors (1, Bootsector)
  285.        16        1       NFATS     number of FAT's (2)
  286.        17        2       NDIRS     max. entries in main directory
  287.        19        2       NSECTS    total sectors
  288.        21        1       MEDIA     media-byte (not used by TOS)
  289.        22        2       SPF       sectors/FAT (5)
  290.        24        2       SPT       sectors/track
  291.        26        2       NSIDES    sides (1 or 2; no joke this time)
  292.        28        2       NHID      hidden sectors (ignored by TOS)
  293.  
  294.        30        2       EXECFLAG  start of bootcode : flag
  295.        32        2       LDMODE    0=load FNAME; <>0=load sectors
  296.        34        2       SSECT     first sector (LDMODE<>0)
  297.        36        2       SECTCNT   number of sectors
  298.        38        4       LDADDR    load at this RAM-address
  299.        42        4       FATBUF    address of FAT-buffer
  300.        46       11       FNAME     filename (nnnnnnnneee) (LDMODE=0)
  301.        57        1       DUMMY     fill-byte
  302.  
  303.        58                          boot-routine (could be a boot-virus)
  304.  
  305.       510        2       CHKSUM
  306.  
  307. TOS determines if the bootsector is executable by adding all bytes. If
  308. this sum (AND &HFFFF) equals &H1234, the bootsector is executable. If you
  309. use GFA-Basic this probably means you have an ancient ST with TOS in RAM,
  310. or a boot-virus. A normal GFA-disk has only &H00- or &HE5-bytes from the
  311. offset 58.
  312.  
  313.                                 ~~~OOOO~~~
  314.  
  315. SOUND and WAVE
  316.  
  317. After a SOUND-command, the sound sometimes continues in spite of the
  318. elapsed time. If the command is followed by another SOUND- or a WAVE-
  319. command, the time is handled correctly. This certainly sounds like a GFA-
  320. bug.
  321.  
  322. The easiest way to stop all sound is :
  323.      WAVE 0,0       ! turn all sound off
  324.  
  325. Sound of a certain frequency can be produced with :
  326.      SOUND ch,vol,#ROUND(125000/freq%),pause
  327.  
  328. Although our ST is not famous for its brilliant sound, you can produce
  329. nice sound-effects with the simple commands SOUND and WAVE. Check out the
  330. Procedures Siren.sound, Tideli.sound, Bounce1.sound and Bounce2.sound to
  331. hear what I mean.
  332.  
  333.  
  334. Dosound (XBIOS 32)
  335.  
  336. XBIOS 32 (Dosound) can be used to play music in a special format. I
  337. propose to use the extension 'X32' for song-files in this format. The
  338. operating system takes care of playing the music during interrupts (every
  339. 1/50th second). Take a look at the Procedures Play.song and Stop.song to
  340. see how you could use XBIOS 32 in your programs. You can even play a song
  341. continuously with the Procedure Play.cont.song. Temporarily stopping a
  342. song is possible with the Procedure Interrupt.song.
  343.  
  344. If you use XBIOS 32 to play music, you are advised to switch the key-click
  345. off. Otherwise the music will stop as soon as the user presses a key.
  346.  
  347. Once I discovered XBIOS 32 did not work during the initialization (mainly
  348. the filling of arrays) of a large program. I had converted the program
  349. from GFA-Basic 2.0 to 3.0, but I did not have the patience to find out
  350. what caused this problem.
  351.  
  352. XBIOS 32 can also be used for sound-effects. I have developed the
  353. Procedure Initio.sound for building sound-strings from a few DATA-lines.
  354. I hereby declare this as the standard method for creating sound-strings.
  355. After @do.sound(sound$) you can hear the sound-effect. In the following
  356. example the sound-string bounce3$ is created :
  357.      PROCEDURE initio.sound
  358.        ' *** commands in DATA-lines :
  359.        ' ***         REG = 14 parameters for registers 0-13
  360.        ' ***         END = end of sound-string
  361.        ' ***         PAUSE = pause (followed by time in 1/50 seconds)
  362.        ' ***         VAR = decrease/increase tone : channel,start,+/-step,
  363.        ' ***                                                     end-value
  364.        '
  365.        bounce3.sound:
  366.        DATA REG,0,0,0,0,0,0,27,248,16,16,16,35,95,0
  367.        DATA VAR,3,255,-1,116
  368.        DATA PAUSE,255,END
  369.        RESTORE bounce3.sound
  370.        @sound.string(bounce3$)
  371.      RETURN
  372.      '
  373.      PROCEDURE sound.string(VAR s$)
  374.        LOCAL n,snd$,snd,channel,begin,step,end
  375.        s$=""
  376.        DO
  377.          READ snd$
  378.          snd$=UPPER$(snd$)
  379.          EXIT IF snd$="END"
  380.          IF snd$="REG"
  381.            FOR n=0 TO 13
  382.              READ snd
  383.              s$=s$+CHR$(n)+CHR$(snd)
  384.            NEXT n
  385.          ENDIF
  386.          IF snd$="PAUSE"
  387.            READ snd
  388.            s$=s$+CHR$(130)+CHR$(snd)
  389.          ENDIF
  390.          IF snd$="VAR"
  391.            READ channel,begin,step,end
  392.            s$=s$+CHR$(128)+CHR$(begin)+CHR$(129)+CHR$(channel)+CHR$(step)
  393.            s$=s$+CHR$(end)
  394.          ENDIF
  395.        LOOP
  396.        s$=s$+CHR$(255)+CHR$(0)               ! terminator
  397.      RETURN
  398.      '
  399.      PROCEDURE do.sound(sound$)
  400.        VOID XBIOS(32,L:VARPTR(sound$))
  401.      RETURN
  402.  
  403.                                 ~~~OOOO~~~
  404.  
  405.                                 13.  MODEM
  406.  
  407.  
  408. INPAUX$
  409.  
  410. With the command INPAUX$ the internal RS232-buffer is read and at the same
  411. time cleared. You can find the address of the input-buffer with :
  412.      adr.in%=LPEEK(XBIOS(14,0))
  413. The output-buffer can be located with :
  414.      adr.out%=LPEEK(XBIOS(14,0)+14)
  415.  
  416.  
  417. INP
  418.  
  419. If you use INP(1) to read incoming bytes, you should always check with
  420. INP?(1) if the RS232-buffer contains data.
  421.  
  422.  
  423. Rsconf (XBIOS 15)
  424.  
  425. With XBIOS 15 (Rsconf) you can change the RS232-parameters. A few
  426. baudrates :
  427.      0 - 19200 baud
  428.      1 -  9600 baud
  429.      4 -  2400 baud
  430.      7 -  1200 baud
  431.      9 -   300 baud
  432.     14 -    75 baud
  433. Use -1 for parameters you don't want to change. Due to a TOS-bug, you
  434. can't use 75 baud, because '14' results in 120 baud. Also, the old TOS
  435. (pre-Blitter age) can't handle hardware handshake with RTS/CTS-signals.
  436. Atari has released a bug-fix that should enable any TOS to use RTS/CTS.
  437. Software handshaking (XON/XOFF) functions properly. The default
  438. after power-up is no handshake protocol.
  439.  
  440.                                 ~~~OOOO~~~
  441.  
  442. Calculations
  443.  
  444. Try to remove all unnecessary calculations from loops, e.g. :
  445.      FOR i=1 TO 1000
  446.        x(i)=2*q*i
  447.      NEXT i
  448. It's a better idea to calculate 2*q outside the loop :
  449.      q2=q*2
  450.      FOR i=1 TO 1000
  451.        x(i)=q2*i
  452.      NEXT i
  453.  
  454. Always try to convert floating point variables to integers before entering
  455. a loop. Then you will be able to use the fast integer-operators. An
  456. obvious example would be a calculation with dollars (24.37) that could be
  457. replaced by a calculation with cents (2437). Use this method if you know
  458. the lowest possible value of the floating point variable (0.01 in this
  459. case) and then divide by this value. But watch out for rounding errors and
  460. integer-overflow.
  461.  
  462. Powers of 2 can be calculated fast by setting a bit :
  463.      x%=BSET(0,6)   ! faster than x%=2^6
  464. And for the ultimate speed-freaks, multiplying with a power of 2 is
  465. slightly faster with SHL :
  466.      y%=SHL(x%,3)   ! faster than y%=MUL(x%,8)
  467. Of course there is no overflow-control if you use SHL (or MUL).
  468.  
  469. Sometimes, calculations in a loop can be replaced by a look-up table :
  470.      FOR i=1 TO 1000
  471.        y%(i)=x|(i)^2
  472.      NEXT i
  473. First, create a table of squares :
  474.      DIM square%(255)
  475.      FOR i=0 TO 255
  476.        square%(i)=i*i
  477.      NEXT i
  478. Then use this table in the loop :
  479.      FOR i=1 TO 1000
  480.        y%(i)=square%(x|(i))
  481.      NEXT i
  482.  
  483.  
  484. FOR ... NEXT
  485.  
  486. I use local variables in Procedures if possible. But if you intend to
  487. compile the program later, you should declare the counter in a FOR ...
  488. NEXT loop as a global variable. In the compiled program, the loop will be
  489. executed faster!
  490.  
  491. If you use floating point count-variables in a FOR ... NEXT loop (or any
  492. other loop), you could encounter unexpected problems :
  493.      FOR i#=0.1 TO 0.9 STEP 0.1
  494.        PRINT i#
  495.      NEXT i#
  496. You would expect 0.9 as the result of the last addition (0.8 + 0.1), but
  497. 0.9 is never printed! This is not a bug in GFA-Basic, but caused by the
  498. internal (binary) representation of floating point numbers. The last
  499. addition results in a number slightly larger than 0.9 and therefore the
  500. loop is left after printing 0.8 . If you insert the line
  501.        i#=ROUND(i#,14)
  502. in the loop, you can solve this problem. But the best solution is to avoid
  503. floating point count-variables in loops. Integer count-variables are much
  504. faster. You could easily change the loop to :
  505.      FOR i=1 TO 9
  506.        PRINT USING "#.#";i/10
  507.      NEXT i
  508. One more time: 'i' is a word-variable, because I use word-variables as
  509. the default for number-variables without postfix.
  510.  
  511. If you use a floating point variable in a REPEAT UNTIL loop, you can avoid
  512. the rounding error by using the special operator '==' :
  513.      i#=0
  514.      REPEAT
  515.        i#=i#+0.1
  516.        PRINT i#
  517.      UNTIL i#==0.9
  518. But you can't use the '=='-operator in a FOR ... NEXT loop.
  519.  
  520. In the following two examples a byte-variable is used as the counter :
  521.      FOR i|=5 DOWNTO -1
  522.        PRINT i|
  523.      NEXT i|
  524.      '
  525.      FOR i|=250 TO 256
  526.        PRINT i|
  527.      NEXT i|
  528. Of course, a byte-variable cannot have a value of -1 or 256. GFA does not
  529. abort with an error-message, but skips the loops. Not a true bug perhaps,
  530. but close.
  531.  
  532.  
  533. Loops
  534.  
  535. Although you can use many different loops in GFA-Basic 3.0, there are
  536. basically only two varieties. You can first test a condition, and then
  537. either continue or leave the loop. Or you can first enter the loop, and
  538. then test a condition to decide if you are going to continue or leave.
  539.  
  540. In an interpreted program the first choice is the fast FOR ... NEXT loop,
  541. then the (slower) REPEAT ... UNTIL loop and finally the (slowest) WHILE
  542. ... WEND loop. In a compiled program all loops are executed equally fast!
  543. If you use a DO ... LOOP, an EXIT IF condition will always take some extra
  544. time.
  545. Try to avoid a negative test in a loop, as this will take more time. E.g.
  546. replace :
  547.      WHILE NOT condition!
  548.        (...)
  549.      WEND
  550. by the much faster :
  551.      DO UNTIL condition!
  552.        (...)
  553.      LOOP
  554. Or similarly replace :
  555.      REPEAT
  556.        (...)
  557.      UNTIL NOT condition!
  558. by the faster :
  559.      DO
  560.        (...)
  561.      LOOP WHILE condition!
  562.  
  563. Finally, you could combine the test of one condition at the start of the
  564. loop with the test of another condition at the end of the loop :
  565.      DO UNTIL condition_1!
  566.        (...)
  567.      LOOP WHILE condition_2!
  568.  
  569.                                 ~~~OOOO~~~
  570.  
  571. CURVE
  572.  
  573. With the command CURVE you can draw a Bezier-curve :
  574.      CURVE x1,y1,x2,y2,x3,y3,x4,y4
  575. The Bezier-curve starts at (x1,y1) and ends at (x4,y4). The other two
  576. points act like little magnets. You can also use this command to draw a
  577. 'normal' curve between two points by letting the points (x3,y3) and
  578. (x4,y4) coincide. Try the following to see what I mean :
  579.      GRAPHMODE 3
  580.      MOUSE x2,y2,k
  581.      DO
  582.        CURVE 10,100,x2,y2,110,100,110,100    ! draw curve
  583.        REPEAT
  584.          MOUSE x,y,k
  585.        UNTIL x<>x2 OR y<>y2
  586.        CURVE 10,100,x2,y2,110,100,110,100    ! erase curve
  587.        x2=x
  588.        y2=y
  589.      LOOP
  590. This method could be used to draw large letters.
  591.  
  592.                                 ~~~OOOO~~~
  593.  
  594. Line-A
  595.  
  596. The Line-A commands are faster than the corresponding VDI-commands in GFA-
  597. Basic. The difference should be even greater after loading GDOS (?). In
  598. the following table you can find how many times faster the Line-A command
  599. is :
  600.       PSET / PLOT  = 3
  601.       PTST / POINT = 2
  602.      HLINE / LINE  = 2
  603.      ARECT / PBOX  = 1.5
  604. The syntax of Line-A commands is more complicated, but that's no problem
  605. for us GFA-experts. Line-A commands use the 'SETCOLOR-index', so you'll
  606. probably need the Standard Array color.index().
  607.  
  608. HLINE
  609.  
  610. An additional advantage of the commands HLINE, ARECT and APOLY is that you
  611. don't have to change the DEFFILL-parameters in the main program. For solid
  612. horizontal lines, use :
  613.      pattern=-1
  614.      adr%=V:pattern
  615.      HLINE x1,y,x2,color,mode,adr%,0
  616. You can't use &X1111111111111111 (16 bits) for the pattern, because bit 15
  617. of a word-variable is a flag for a negative number. Yes, that's why the
  618. largest positive word is 2^15 - 1 (32767). The solution to this little
  619. problem is to assign -1 to the word-variable. You have my word, now all 16
  620. bits are 1. Use BIN$ if you don't believe me.
  621.  
  622. For very complicated patterns you could use a word-array :
  623.      DIM pattern(i)
  624.      adr%=V:pattern(0)
  625.      (...)               ! put fill-pattern in pattern(0) to pattern(i)
  626.      HLINE x1,y,x2,color,mode,adr%,i
  627.  
  628.                                 ~~~OOOO~~~
  629.  
  630. Blitter
  631.  
  632. The Blitter-TOS (1987) allows you to switch the Blitter on/off. I couldn't
  633. test the following Procedure, because I don't have a Blitter. But if I
  634. understand the function XBIOS 64 (Blitmode) correctly, you could switch
  635. the Blitter on and off from GFA-Basic :
  636.      PROCEDURE blitter(switch!)
  637.        LOCAL status
  638.        status=XBIOS(64,-1)
  639.        IF BTST(status,1)           ! Blitter available?
  640.          IF switch!
  641.            status=BSET(status,0)   ! Blitter on
  642.          ELSE
  643.            status=BCLR(status,0)   ! Blitter off
  644.          ENDIF
  645.          ~XBIOS(64,status)         ! do it
  646.        ENDIF
  647.      RETURN
  648.  
  649. By the way, Line A commands do not use the Blitter. The Blitter-chip
  650. contains a hardware-routine that replaces the Line A BitBlt-function
  651. (BITBLT in GFA-Basic). All Mega ST's have a Blitter installed.
  652.  
  653.                                 ~~~OOOO~~~
  654.  
  655. Read this paragraph carefully, before using the GFAXPERT-files. The files
  656. are not Public Domain!
  657.  
  658. You are free to use and change all GFAXPERT-files, but only for personal
  659. use. Certainly not for commercial use.
  660.  
  661. You are invited to copy the original GFAXPERT-disk or the GFAXPRTx.ARC-
  662. files and give these to your friends. But you are not allowed to change
  663. anything on the disk or in the files. If you feel the urge to change
  664. something, don't do it, but write to me (read the chapter 'EPILOGUE').
  665.  
  666. You are not allowed to sell (files from) the GFAXPERT-disk or one of the
  667. GFAXPRTx.ARC-files. The disk GFAXPERT may only be sold by so-called Public
  668. Domain Clubs if they have my written permission to do so. BBS's are free
  669. to make the original GFAXPRTx.ARC-files available for downloading.
  670.  
  671. Any part from the text GFAXPERT.DOC or the Procedure-library GFAXPERT.LIB
  672. may be quoted in newsletters or magazines, if accompanied by a reference
  673. like :
  674.       from GFAXPERT (2nd ed.) by Han Kempen
  675.  
  676. I cannot be held responsible for any damage that may result from running a
  677. GFAXPERT-program, using a Procedure from the library GFAXPERT.LIB, or
  678. using information from this text.
  679.  
  680.  
  681. (c) Han Kempen, 3 July 1990
  682.  
  683.  
  684.                                  EPILOGUE
  685.  
  686.  
  687. Well, that's all folks. I'm quite certain there are still a few bugs to be
  688. found in this text and in the Procedure-Library GFAXPERT.LIB. By now you
  689. should have become an expert in GFA-Basic 3.0, so you will be able to spot
  690. them bugs immediately. Please let me know if you find one.
  691.  
  692. Perhaps you still have some unanswered questions about GFA-Basic. Or an
  693. answer to one of my own questions in this text. Or some neat Procedures.
  694. Or a brilliant program. I would appreciate it very much if you would send
  695. your letter and/or disk to :
  696.  
  697.      Han Kempen
  698.      Rubensstraat 12
  699.      7741 AR Coevorden
  700.      the Netherlands
  701.  
  702. Do share your ideas, Procedures and programs with others, starting with
  703. me. Consider it a small payment for the GFAXPERT-files. Thanks.
  704.  
  705.                                 ~~~OOOO~~~
  706.  
  707.